﻿using System;
using System.Web;
using System.Linq;
using System.Web.UI;
using System.Xml;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using System.Security.Permissions;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using SharePointListSecurity.Model;
using Microsoft.SharePoint.Utilities;

namespace SharePointListSecurity.WebControls
{
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal), SharePointPermission(SecurityAction.InheritanceDemand, ObjectModel = true), AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
    public class AdditionalPageHeadControl : WebControl
    {
        #region Overridden Methods

        protected override void CreateChildControls()
        {

            if (FeatureIds.IsFeatureActivated())
            {
                try
                {
                    var webParts = GetXsltListViewWebParts();

                    if (webParts != null)
                    {
                        var listSecurityService = new SharepointListSecurityService();
                        foreach (XsltListViewWebPart webPart in webParts)
                        {
                            SPList currentList = SPContext.Current.Web.Lists[webPart.ListId];
                            var hidenFields = listSecurityService.GetHiddenFields(currentList, SPControlMode.Display);
                         var views=   currentList.Views;

                            if (hidenFields.Count > 0)
                                webPart.XmlDefinition = HideFields(hidenFields, webPart.XmlDefinition);

                            var readOnlyFields = listSecurityService.GetReadOnlyFields(currentList);
                            if (readOnlyFields.Count > 0)
                                webPart.XmlDefinition = MakeFieldsReadOnly(readOnlyFields, webPart.XmlDefinition);
                        }
                    }
                }
                catch
                {

                }
                base.CreateChildControls();
            }
        }

        #endregion

        #region Private Methods
        private IEnumerable<XsltListViewWebPart> GetXsltListViewWebParts()
        {
            WebPartManager webPartManager = WebPartManager.GetCurrentWebPartManager(this.Page);

            if (webPartManager != null)
            {
                return webPartManager.WebParts.OfType<XsltListViewWebPart>().ToList();
            }
            return null;
        }
        private string HideFields(IEnumerable<SPField> spFields, string xsltListViewWebPart)
        {
            try
            {
                var spFieldsStaticNames = spFields.Select(f => f.StaticName).ToList();
                var titleStaticNames = new List<string> { "Title", "LinkTitle", "LinkTitleNoMenu" };
                var nameStaticNames = new List<string> { "FileLeafRef", "LinkFilename", "LinkFilenameNoMenu" };

                if (spFieldsStaticNames.Intersect(titleStaticNames).Count() > 0)
                    spFieldsStaticNames = spFieldsStaticNames.Union(titleStaticNames).ToList();

                if (spFieldsStaticNames.Intersect(nameStaticNames).Count() > 0)
                    spFieldsStaticNames = spFieldsStaticNames.Union(nameStaticNames).ToList();

                var filter = String.Join(" or ", spFieldsStaticNames.Select(f => String.Format("@Name =\"{0}\"", f)).ToArray());

                var query = String.Format("View/ViewFields/FieldRef[{0}] | View/Query/GroupBy/FieldRef[{0}]", filter);

                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(xsltListViewWebPart);

                var nodes = xmlDocument.SelectNodes(query);
                foreach (XmlNode node in nodes)
                {
                    var parent = node.ParentNode;
                    parent.RemoveChild(node);
                    if (parent.ChildNodes.Count == 0)
                        parent.ParentNode.RemoveChild(parent);
                }

                return xmlDocument.InnerXml;
            }
            catch //(Exception ex)
            {
                return xsltListViewWebPart;
            }
        }
        private string MakeFieldsReadOnly(IEnumerable<SPField> spFields, string xsltListViewWebPart)
        {
            try
            {
                var spFieldsStaticNames = spFields.Select(f => f.StaticName).ToList();
                var titleStaticNames = new List<string> { "Title", "LinkTitle", "LinkTitleNoMenu" };

                if (spFieldsStaticNames.Intersect(titleStaticNames).Count() > 0)
                    spFieldsStaticNames = spFieldsStaticNames.Union(titleStaticNames).ToList();

                var filter = String.Format("View/ViewFields/FieldRef[{0}]",
                                            String.Join(" or ",
                                                    spFieldsStaticNames.Select(f => String.Format("@Name =\"{0}\"", f)).ToArray()));

                var xmlDocument = new XmlDocument();
                xmlDocument.LoadXml(xsltListViewWebPart);

                var nodes = xmlDocument.SelectNodes(filter);
                foreach (XmlNode node in nodes)
                {
                    var attribute = node.Attributes["ReadOnly"];
                    if (attribute == null)
                    {
                        attribute = xmlDocument.CreateAttribute("ReadOnly");
                        node.Attributes.Append(attribute);
                    }
                    attribute.Value = "TRUE";
                }

                return xmlDocument.InnerXml;
            }
            catch //(Exception ex)
            {
                return xsltListViewWebPart;
            }
        }
        #endregion
   
    }
}